#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

typedef struct can_frame CAN_FRAME;

unsigned char hex_tmp[100] = {0};
/**
 * @brief : hexstring_to_hexnumber
 * @param  str_buf :输入要转换的字符串数组         
 * @param  convert_len : 输入要转换的长度     
 * @param  hex_buf :输出转换后的hex数组          
 * @param  hex_size :输入hex数组最大可用长度        
 * @return unsigned int :输出转换后的hex数组长度 
 */
int hexstring_to_hexnumber(char *str_buf, unsigned int convert_len, unsigned char *hex_buf, unsigned int hex_size)
{
    if (!str_buf || !hex_buf) return 0;
    if (hex_size < (convert_len / 2) + (convert_len % 2)) return 0;

    unsigned char hex_u8 = 0;
    int hex_len = 0;
    for (unsigned int i = 0; i < convert_len; i++)
    {
        if ('0' <= str_buf[i] && str_buf[i] <= '9')
        {
            hex_u8 = str_buf[i] - '0';
        }
        else if ('A' <= str_buf[i] && str_buf[i] <= 'F')
        {
            hex_u8 = str_buf[i] - 'A' + 10;
        }
        else if ('a' <= str_buf[i] && str_buf[i] <= 'f')
        {
            hex_u8 = str_buf[i] - 'a' + 10;
        }
        else
        {
            hex_u8 = 0xFF;
        }

        if (0xFF != hex_u8)
        {
            if (0 == i % 2)
            {
                hex_buf[i / 2] = hex_u8 << 4;
                hex_len++;
            }
            else
            {
                hex_buf[i / 2] |= hex_u8;
            }
        }
        else
        {
            return -1;
        }
    }

    return hex_len;
}

int socketCan(int *psockfd)
{
	struct ifreq ifr = {0};
    struct sockaddr_can can_addr = {0};
    int ret;

	if(psockfd == NULL)
	{
        perror("Input psockfd is NULL!");
        return -1;
	}
	
    //打开套接字
    *psockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if(0 > *psockfd)
    {
        perror("socket error!");
        return -1;
    }

    //指定 can0 设备
    strcpy(ifr.ifr_name, "can0");
    ioctl(*psockfd, SIOCGIFINDEX, &ifr);
    can_addr.can_family = AF_CAN;
    can_addr.can_ifindex = ifr.ifr_ifindex;

    //将 can0 与套接字进行绑定
    ret = bind(*psockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
    if(0 > ret)
    {
        perror("bind socket error!");
        close(*psockfd);
        return -1;
    }
	return 0;
}

int getSendFrame(CAN_FRAME *ptFrame, char **argv)
{
	unsigned int id_len = 0;
    int len = 0;
    unsigned int i = 0;

	if (argv[1] != NULL)
    {
	    sscanf(argv[1], "%x", &ptFrame->can_id);

        id_len = strlen(argv[1]);
        switch(id_len)
        {
            case 3:
                printf("\nSend CAN_ID: <%x> ", ptFrame->can_id);
                break;
            case 8:
                printf("\nSend CAN_ID: <%x> ", ptFrame->can_id);
                ptFrame->can_id |= CAN_EFF_FLAG;
                break;
            default:
                printf("\nInput CAN_ID error! CAN_ID: <%x> \n", ptFrame->can_id);
				return -1;
        }
    }
    else
    {
        printf("\nInput CAN_ID error!\n");
        return -1;
        // ptFrame->can_id = 0x123;
        // printf("\nDefault Send CAN_ID: <%x> ", ptFrame->can_id);
    }

    if (argv[2] != NULL)
    {
	    //获取要发送的CAN data
        len = hexstring_to_hexnumber(argv[2], strlen(argv[2]), hex_tmp, sizeof(hex_tmp));
        if(len < 0 || len > 8)
        {
            printf("\nWrong data format! DATA 0-F\n");
            return -1;
        }

	    ptFrame->can_dlc = len;
        printf("DLC: <%u> , DATA:", ptFrame->can_dlc);
        for (i = 0; i < len; i++)
	    {
		    printf(" %02X ", hex_tmp[i]);
            ptFrame->data[i] = hex_tmp[i];
	    }
    }
    else
    {
        //ptFrame->data[0] = 0x1a;
        ptFrame->can_dlc = 0;
		//printf("\nDefault Send DLC: <%u> , DATA: %02X ", ptFrame->can_dlc, ptFrame->data[0]);
    }
	return 0;
}

int main(int argc, char **argv)
{
    CAN_FRAME frame = {0};
    int sockfd = -1;
    int ret, status, i;

	unsigned int num = 0;
	unsigned int len = 0;

   // printf("argv[1]:%s\n", argv[1]);
    if(strcmp(argv[1], "-h") == 0)
    {
        printf("\nsend <CAN_ID> <DATA>\n CAN_ID len 3 or 8\n DATA 0-F\n");
        return 0;
    }
	
	if (0 > socketCan(&sockfd))
	{
		return 0;
	}

    if (0 > getSendFrame(&frame, argv))
    {
        close(sockfd);
        return 0;
    }

//设置过滤规则， 不接收任何报文，仅发送数据
    setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

    ret = write(sockfd, &frame, sizeof(frame));

    if(sizeof(frame) != ret)
    {
        printf("\nwrite error!\n");
        close(sockfd);
        return 0;
    }

    if (frame.can_id & CAN_EFF_FLAG)
	{
        printf("\n[CAN] Send Extended Frames Successfully!\n");
	}
	else
	{
		printf("\n[CAN] Send Standard Frames Successfully!\n");
	}

//关闭套接字
    close(sockfd);
    return 0;
}